from fastapi import HTTPException, Request, status
from fastapi.responses import JSONResponse
from typing import Optional, Dict, Any
import logging
from datetime import datetime

from backend.schemas.responses import ErrorResponse, ErrorCode

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class BaseAPIException(HTTPException):
    """API异常基类"""
    
    def __init__(
        self,
        message: str,
        error_code: ErrorCode,
        status_code: int = status.HTTP_400_BAD_REQUEST,
        details: Optional[Dict[str, Any]] = None
    ):
        self.message = message
        self.error_code = error_code
        self.details = details or {}
        super().__init__(status_code=status_code, detail=message)

class ValidationException(BaseAPIException):
    """参数验证异常"""
    
    def __init__(self, message: str = "参数验证失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.VALIDATION_ERROR,
            status_code=status.HTTP_400_BAD_REQUEST,
            details=details
        )

class AuthenticationException(BaseAPIException):
    """认证异常"""
    
    def __init__(self, message: str = "认证失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.AUTHENTICATION_FAILED,
            status_code=status.HTTP_401_UNAUTHORIZED,
            details=details
        )

class AuthorizationException(BaseAPIException):
    """授权异常"""
    
    def __init__(self, message: str = "权限不足", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.AUTHORIZATION_FAILED,
            status_code=status.HTTP_403_FORBIDDEN,
            details=details
        )

class ResourceNotFoundException(BaseAPIException):
    """资源不存在异常"""
    
    def __init__(self, message: str = "资源不存在", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.RESOURCE_NOT_FOUND,
            status_code=status.HTTP_404_NOT_FOUND,
            details=details
        )

class BusinessException(BaseAPIException):
    """业务逻辑异常"""
    
    def __init__(
        self,
        message: str,
        error_code: ErrorCode,
        details: Optional[Dict[str, Any]] = None
    ):
        super().__init__(
            message=message,
            error_code=error_code,
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            details=details
        )

class InternalServerException(BaseAPIException):
    """服务器内部异常"""
    
    def __init__(self, message: str = "服务器内部错误", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.INTERNAL_SERVER_ERROR,
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            details=details
        )

# 具体业务异常
class InvalidDateFormatException(ValidationException):
    """日期格式错误异常"""
    
    def __init__(self, message: str = "日期格式错误", details: Optional[Dict[str, Any]] = None):
        super().__init__(message=message, details=details)
        self.error_code = ErrorCode.INVALID_DATE_FORMAT

class DataNotFoundException(ResourceNotFoundException):
    """数据不存在异常"""
    
    def __init__(self, message: str = "数据不存在", details: Optional[Dict[str, Any]] = None):
        super().__init__(message=message, details=details)
        self.error_code = ErrorCode.DATA_NOT_FOUND

class PredictionFailedException(BusinessException):
    """预测失败异常"""
    
    def __init__(self, message: str = "预测计算失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.PREDICTION_FAILED,
            details=details
        )

class InvalidCredentialsException(AuthenticationException):
    """凭证无效异常"""
    
    def __init__(self, message: str = "用户名或密码错误", details: Optional[Dict[str, Any]] = None):
        super().__init__(message=message, details=details)
        self.error_code = ErrorCode.INVALID_CREDENTIALS

# 全局异常处理器
async def global_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """全局异常处理器"""
    
    # 记录异常日志
    logger.error(f"Exception occurred: {type(exc).__name__}: {str(exc)}", exc_info=True)
    
    if isinstance(exc, BaseAPIException):
        # 自定义API异常
        error_response = ErrorResponse.create(
            message=exc.message,
            error_code=exc.error_code
        )
        return JSONResponse(
            status_code=exc.status_code,
            content=error_response.dict()
        )
    
    elif isinstance(exc, HTTPException):
        # FastAPI HTTP异常
        error_response = ErrorResponse.create(
            message=exc.detail,
            error_code=ErrorCode.INTERNAL_SERVER_ERROR
        )
        return JSONResponse(
            status_code=exc.status_code,
            content=error_response.dict()
        )
    
    else:
        # 未预期的异常
        error_response = ErrorResponse.create(
            message="服务器内部错误",
            error_code=ErrorCode.INTERNAL_SERVER_ERROR
        )
        return JSONResponse(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            content=error_response.dict()
        )

async def validation_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """参数验证异常处理器"""
    
    logger.warning(f"Validation error: {str(exc)}")
    
    # 提取验证错误详情
    details = {}
    if hasattr(exc, 'errors') and callable(getattr(exc, 'errors', None)):
        try:
            validation_errors = exc.errors()  # type: ignore
            details = {"validation_errors": validation_errors}
            logger.warning(f"Validation details: {validation_errors}")
        except Exception as e:
            logger.error(f"Error extracting validation details: {e}")
    
    # 构造更详细的错误消息
    error_message = "请求参数验证失败"
    if details.get("validation_errors"):
        # 提取第一个错误作为主要错误消息
        first_error = details["validation_errors"][0]
        if "msg" in first_error:
            error_message = f"请求参数验证失败: {first_error['msg']}"
    
    error_response = ErrorResponse.create(
        message=error_message,
        error_code=ErrorCode.VALIDATION_ERROR
    )
    
    # 手动添加details到响应中
    response_data = error_response.dict()
    if details:
        response_data["details"] = details
    
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=response_data
    )

# 异常处理装饰器已移除，使用全局异常处理器 